package com.zntech.app.common.accessibility

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.graphics.Rect
import android.os.IBinder
import android.os.RemoteException
import android.util.Log
import com.zntech.app.common.IInstantAssist
import com.zntech.app.common.accessibility.bean.AssistSiblingResult
import com.zntech.app.common.accessibility.bean.InstantAssistText
import com.zntech.app.common.shell.ShellResult

object InstantAssistClient {
    private const val TAG: String = "InstantAssistClient"
    private var mAssistBinder: IInstantAssist? = null
    private var mApplicationContext: Context? = null

    fun init(context: Context) {
        mApplicationContext = context;
        reconnectService()
    }

    fun destroy() {
        mApplicationContext?.unbindService(mServiceConnection)
    }

    fun getPageText(rc: Rect?): List<InstantAssistText>? {

        if (mAssistBinder?.asBinder()?.isBinderAlive == true) {
            try {
                return mAssistBinder?.getPageText(rc)
            } catch (e: RemoteException) {
                Log.d(TAG, "instant accessibility binder getPageText exception")
                reconnectService()
            }
        } else {
            Log.d(TAG, "instant accessibility binder getPageText died")
            reconnectService()
        }

        return null
    }

    fun findByText(text: String): Rect? {

        if (mAssistBinder?.asBinder()?.isBinderAlive == true) {
            try {
                return mAssistBinder?.findByText(text)
            } catch (e: RemoteException) {
                Log.d(TAG, "instant accessibility binder findByText exception")
                reconnectService()
            }
        } else {
            Log.d(TAG, "instant accessibility binder findByText died")
            reconnectService()
        }
        return null
    }

    fun findById(id: String): Rect? {
        if (mAssistBinder?.asBinder()?.isBinderAlive == true) {
            try {
                return mAssistBinder?.findById(id)
            } catch (e: RemoteException) {
                Log.d(TAG, "instant accessibility binder findById exception")
                reconnectService()
            }
        } else {
            Log.d(TAG, "instant accessibility binder findById died")
            reconnectService()
        }
        return null
    }

    fun findAllByText(text: String): List<Rect>? {
        if (mAssistBinder?.asBinder()?.isBinderAlive == true) {
            try {
                return mAssistBinder?.findAllByText(text)
            } catch (e: RemoteException) {
                Log.d(TAG, "instant accessibility binder findAllByText exception")
                reconnectService()
            }
        } else {
            Log.d(TAG, "instant accessibility binder findAllByText died")
            reconnectService()
        }
        return null
    }

    fun findAllById(id: String): List<Rect>? {
        if (mAssistBinder?.asBinder()?.isBinderAlive == true) {
            try {
                return mAssistBinder?.findAllById(id)
            } catch (e: RemoteException) {
                Log.d(TAG, "instant accessibility binder findAllById exception")
                reconnectService()
            }
        } else {
            Log.d(TAG, "instant accessibility binder findAllById died")
            reconnectService()
        }
        return null
    }
    fun getPageInfo(): List<InstantAssistText>?{
        if (mAssistBinder?.asBinder()?.isBinderAlive == true) {
            try {
                return mAssistBinder?.pageInfo
            } catch (e: RemoteException) {
                Log.d(TAG, "instant accessibility binder getPageInfo exception")
                reconnectService()
            }
        } else {
            Log.d(TAG, "instant accessibility binder getPageInfo died")
            reconnectService()
        }
        return null
    }

    fun getPageInfoByIds(
        rcLimit: Rect?,
        vararg ids: String,
        isIntersection: Boolean = true,
    ): List<InstantAssistText>? {
        if (mAssistBinder?.asBinder()?.isBinderAlive == true) {
            try {
                return mAssistBinder?.getPageInfoByIds(rcLimit, ids.asList(), isIntersection)
            } catch (e: RemoteException) {
                Log.d(TAG, "instant accessibility binder getPageInfoByIds exception")
                reconnectService()
            }
        } else {
            Log.d(TAG, "instant accessibility binder getPageInfoByIds died")
            reconnectService()
        }
        return null
    }

    fun findAllByIdAndSiblingIds(
        rcLimit: Rect?,
        mainId: String,
        vararg siblingIds: String,
        isIntersection: Boolean = true,
    ): List<AssistSiblingResult>? {
        if (mAssistBinder?.asBinder()?.isBinderAlive == true) {
            try {
                return mAssistBinder?.findAllByIdAndSiblingIds(
                    rcLimit,
                    mainId,
                    siblingIds.asList(),
                    isIntersection
                )
            } catch (e: RemoteException) {
                Log.d(TAG, "instant accessibility binder findAllByIdAndSiblingIds exception")
                reconnectService()
            }
        } else {
            Log.d(TAG, "instant accessibility binder findAllByIdAndSiblingIds died")
            reconnectService()
        }
        return null
    }

    fun pasteText(text: String, x: Float, y: Float): Boolean? {
        if (mAssistBinder?.asBinder()?.isBinderAlive == true) {
            try {
                return mAssistBinder?.pasteText(text, x, y)
            } catch (e: RemoteException) {
                Log.d(TAG, "instant accessibility binder pasteText x,y exception")
                reconnectService()
            }
        } else {
            Log.d(TAG, "instant accessibility binder pasteText x,y died")
            reconnectService()
        }
        return false
    }

    fun pasteText(text: String, viewId: String): Boolean? {
        if (mAssistBinder?.asBinder()?.isBinderAlive == true) {
            try {
                return mAssistBinder?.pasteTextById(text, viewId)
            } catch (e: RemoteException) {
                Log.d(TAG, "instant accessibility binder pasteText viewId exception")
                reconnectService()
            }
        } else {
            Log.d(TAG, "instant accessibility binder pasteText viewId died")
            reconnectService()
        }
        return false
    }

    fun execShell(cmd: String): ShellResult {
        val result = ShellResult(cmd, -1, null, "exec failed, shell do not connect")
        if (mAssistBinder?.asBinder()?.isBinderAlive == true) {
            try {
                return mAssistBinder?.execShell(cmd) ?: result
            } catch (e: RemoteException) {
                Log.d(TAG, "instant accessibility binder shell exception")
                reconnectService()
            }
        } else {
            Log.d(TAG, "instant accessibility binder shell died")
            reconnectService()
        }
        return result
    }


    val mServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            mAssistBinder = IInstantAssist.Stub.asInterface(service);
            try {
                service!!.linkToDeath(mDeathRecipient!!, 0);
            } catch (e: RemoteException) {
                e.printStackTrace()
            }
        }

        override fun onServiceDisconnected(name: ComponentName?) {

        }
    }
    var mDeathRecipient: IBinder.DeathRecipient? = null
    private fun reconnectService() {
        val intent = Intent()
        intent.action = "com.zntech.instant.accessibility.InstantAssistApiService"
        intent.setPackage("com.haitang.app")

        if (mDeathRecipient != null) {
            mAssistBinder?.asBinder()?.unlinkToDeath(mDeathRecipient!!, 0);
            mDeathRecipient = null
        }

        mDeathRecipient = IBinder.DeathRecipient {
            if (mAssistBinder == null)
                return@DeathRecipient
            Log.d(TAG, "link death restart service")
            mAssistBinder!!.asBinder().unlinkToDeath(mDeathRecipient!!, 0);
            mAssistBinder = null
            mApplicationContext?.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE)
        }

        mApplicationContext?.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE)
    }
}